package aliyun

import (
	"fmt"
	"os"

	"gitee.com/east-rise/cloud-station/store"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

// 定义AliOssStore满足store.Uploader接口，确保AliOssStore可以被作为上传器使用。
var (
	_ store.Uploader = &AliOssStore{}
)

// Options 结构体用于存储 AliOssStore 的配置选项
type Options struct {
	Endpoint     string // OSS 服务的访问域名
	AccessKey    string // 阿里云访问密钥 ID
	AccessSecret string // 阿里云访问密钥 Secret
}

// Validate 检查配置选项是否有效
// 如果 Endpoint、AccessKey 或 AccessSecret 中有任何一个为空，则返回错误
func (o *Options) Validate() error {
	if o.Endpoint == "" || o.AccessKey == "" || o.AccessSecret == "" {
		return fmt.Errorf("endpoint, access_key access_secret has one empty")
	}

	return nil
}

// NewDefaultAliOssStore 创建一个使用环境变量配置的 AliOssStore 实例
// 返回一个初始化好的 AliOssStore 指针和可能发生的错误
// 环境变量要求包括 ALI_OSS_ENDPOINT（OSS 终端节点）、ALI_AK（阿里云访问密钥 ID）和 ALI_SK（阿里云访问密钥 Secret）
func NewDefaultAliOssStore() (*AliOssStore, error) {
	return NewAliOssStore(&Options{
		Endpoint:     os.Getenv("ALI_OSS_ENDPOINT"),
		AccessKey:    os.Getenv("ALI_AK"),
		AccessSecret: os.Getenv("ALI_SK"),
	})
}

// NewAliOssStore 根据提供的配置选项创建一个新的 AliOssStore 实例
// opts: 配置选项的指针，包含 Endpoint、AccessKey 和 AccessSecret
// 返回一个初始化好的 AliOssStore 指针和可能发生的错误
func NewAliOssStore(opts *Options) (*AliOssStore, error) {
	// 验证配置选项的有效性
	if err := opts.Validate(); err != nil {
		return nil, err
	}

	// 使用配置选项创建 OSS 客户端
	c, err := oss.New(opts.Endpoint, opts.AccessKey, opts.AccessSecret)
	if err != nil {
		return nil, err
	}
	// 返回初始化好的 AliOssStore 实例
	return &AliOssStore{
		client: c,
	}, nil
}

// AliOssStore定义了与阿里云OSS交互的结构体。
type AliOssStore struct {
	client *oss.Client // oss.Client实例用于执行OSS操作。
}

// Upload将指定的文件上传到OSS的指定bucket，并输出下载URL。
// bucketName: 上传文件的目标bucket名称。
// objectKey: 上传后文件在OSS中的key。
// fileName: 要上传的本地文件名称。
// 返回值: 上传过程中可能发生的错误。
func (s *AliOssStore) Upload(bucketName string, objectKey string, fileName string) error {
	// 获取指定名称的bucket实例。
	bucket, err := s.client.Bucket(bucketName)
	if err != nil {
		return err
	}

	// 从本地文件上传至OSS。
	if err := bucket.PutObjectFromFile(objectKey, fileName); err != nil {
		return err
	}

	// 生成文件的下载URL，有效期为1天。
	downloadURL, err := bucket.SignURL(objectKey, oss.HTTPGet, 60*60*24)
	if err != nil {
		return err
	}
	// 打印文件的下载URL，提示用户在1天内下载。
	fmt.Printf("文件下载URL: %s \n", downloadURL)
	fmt.Println("请在1天之内下载.")
	return nil
}
